package com.ylx.core.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.ValueFilter;
import com.ylx.core.utils.Base64Util;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;

/**
 * 5G快签签名工具类
 * @author copy from demo
 */
@Slf4j
public final class FastSignSignUtil {

	public static final SerializerFeature SERIALIZER_FEATURE = SerializerFeature.MapSortField;
	public static final String ALGORITHM_SHA256WITHRSA = "SHA256withRSA";
	public static final String ALGORITHM_HMACSHA256 = "HmacSHA256";

	/**
     * 全局数组
     */
    private static final String[] hexDigits = { "0", "1", "2", "3", "4", "5",
            "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };

    private static final Set<String> SENSITIVE_SET = new HashSet<>();

    private static final ValueFilter SENSITIVE_VALUE_FILTER = new ValueFilter() {
        @Override
        public Object process(Object o, String s, Object o1) {
            if (o1 instanceof String) {
                if (SENSITIVE_SET.contains(s)) {
                    return Base64Util.encode((String) o1,Base64Util.CHARSET_NAME_U8);
                }
            }
            return o1;
        }
    };

    public static ValueFilter getSensitiveValueFilter() {
        return SENSITIVE_VALUE_FILTER;
    }

	/**
	 * 使用私钥进行签名
	 */
	public static byte [] signByPK(byte[] original,PrivateKey pk,String algorithm){
		byte[] data = null;
		try {
			Signature sig = Signature.getInstance(algorithm);
			sig.initSign(pk);
			sig.update(original);
			data = sig.sign();
		} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
            log.error("使用私钥签名失败: {}", original,e);
		}
        return data;
	}

    public static String encryptWithKeyToHEX(JSONObject request, String hmacAlgName, String secretKey) {
        try {
            //对json进行排序，SERIALIZER_FEATURE ：SerializerFeature.MapSortField
			String preSign = JSON.toJSONString(request, SERIALIZER_FEATURE);
            SecretKey key = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), hmacAlgName);
            Mac mac = Mac.getInstance(hmacAlgName);
            mac.init(key);
            mac.update(preSign.getBytes(StandardCharsets.UTF_8));
            byte[] out = mac.doFinal();

            String hexString = byteArrayToHexString(out);
            return hexString.toUpperCase(Locale.ENGLISH);
        } catch (Exception e) {
            log.error("签名失败: {}",JSON.toJSONString(request, getSensitiveValueFilter()),e);
        }
        return null;
    }



    /**
     * 转换字节数组为十六进制字符串
     * @param bytes 字节数组
     * @return 十六进制字符串
     */
    private static String byteArrayToHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte aByte : bytes) {
            sb.append(byteToHexString(aByte));
        }
        return sb.toString();
    }
    
    /** 
     * 将一个字节转化成十六进制形式的字符串 
     * @param b 字节数组 
     * @return 字符串 
     */  
    private static String byteToHexString(byte b) {  
        int ret = b;
        if (ret < 0) {  
            ret += 256;  
        }  
        int m = ret / 16;  
        int n = ret % 16;  
        return hexDigits[m] + hexDigits[n];  
    }

    private FastSignSignUtil() {

    }
}
